use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use anyhow::Result;
use halo_model::ExtensionOperator;

use crate::config::app_error::AppResult;
use crate::di::services::{ExtensionStoreService, DatabaseService};
use crate::extension::model::role::{Role, HIDDEN_LABEL_NAME, ROLE_AGGREGATE_LABEL_PREFIX};
use crate::extension::model::role;

/// 使用依赖注入的角色服务实现
/// 
/// 这个服务不依赖全局状态，而是通过构造函数注入所需的依赖
pub struct RoleServiceDI {
    store_service: Arc<ExtensionStoreService>,
}

impl RoleServiceDI {
    /// 创建新的角色服务实例
    pub fn new(store_service: Arc<ExtensionStoreService>) -> Self {
        Self { store_service }
    }

    /// 根据角色名称列表获取角色
    pub async fn list(&self, role_names: &HashSet<String>) -> AppResult<Vec<Role>> {
        let mut roles = Vec::new();
        for role_name in role_names {
            // 这里需要实现从store_service获取角色的逻辑
            // 暂时跳过实际的数据库操作
            // let role = self.store_service.fetch(role::Role::KIND, role_name).await?;
            // roles.push(role);
        }
        Ok(roles)
    }

    /// 获取角色权限列表
    pub async fn list_permissions(&self, names: &HashSet<String>) -> AppResult<Vec<Role>> {
        if self.contains_super_role(names) {
            // 如果包含超级角色，返回所有角色
            return self.list_all_roles_with_filter(true).await;
        }
        
        // 否则返回依赖的角色
        self.list_dependencies(names, true).await
    }

    /// 检查是否包含超级角色
    fn contains_super_role(&self, names: &HashSet<String>) -> bool {
        names.contains("super-role")
    }

    /// 获取所有角色（带过滤）
    async fn list_all_roles_with_filter(&self, filter_hidden: bool) -> AppResult<Vec<Role>> {
        // 这里需要实现从store_service获取所有角色的逻辑
        // 暂时返回空列表
        Ok(Vec::new())
    }

    /// 获取角色依赖
    async fn list_dependencies(&self, names: &HashSet<String>, filter_hidden: bool) -> AppResult<Vec<Role>> {
        let roles = self.list_roles(names, filter_hidden).await?;
        let mut visited = HashSet::new();
        let mut all_roles = Vec::new();

        for role in roles {
            let name = role.get_metadata().get_name();
            if !visited.contains(&name) {
                visited.insert(name);

                // 获取角色的依赖信息
                let dependencies = self.get_role_dependencies(&role)?;
                
                let deps = dependencies
                    .iter()
                    .filter(|&t| !visited.contains(t))
                    .cloned()
                    .collect::<HashSet<String>>();
                
                let dependent_roles = self.list_roles(&deps, filter_hidden).await?;
                all_roles.extend(dependent_roles);
            }
        }
        
        // 获取聚合角色
        let aggregate_roles = self.list_aggregate_roles(&visited, filter_hidden).await?;
        all_roles.extend(aggregate_roles);

        Ok(all_roles)
    }

    /// 获取角色的依赖信息
    fn get_role_dependencies(&self, role: &Role) -> AppResult<Vec<String>> {
        let dependencies_json = role.get_metadata().get_annotation(HIDDEN_LABEL_NAME);
        
        let dependencies: Vec<String> = match dependencies_json {
            Some(s) => serde_json::from_str(s).unwrap_or_else(|_| Vec::new()),
            None => Vec::new(),
        };
        
        Ok(dependencies)
    }

    /// 根据名称和过滤条件获取角色列表
    async fn list_roles(&self, names: &HashSet<String>, filter_hidden: bool) -> AppResult<Vec<Role>> {
        // 这里需要实现从store_service获取角色的逻辑
        // 暂时返回空列表
        Ok(Vec::new())
    }

    /// 获取聚合角色
    async fn list_aggregate_roles(&self, role_names: &HashSet<String>, filter_hidden: bool) -> AppResult<Vec<Role>> {
        let aggregated_label_names: Vec<String> = role_names
            .iter()
            .map(|role_name| format!("{}{}", ROLE_AGGREGATE_LABEL_PREFIX, role_name))
            .collect();

        // 这里需要实现聚合角色的查询逻辑
        // 暂时返回空列表
        Ok(Vec::new())
    }

    /// 检查角色是否应该被隐藏
    fn should_filter_hidden(&self, role: &Role, filter_hidden: bool) -> bool {
        if !filter_hidden {
            return true;
        }
        
        let labels = role.get_metadata().get_labels();
        if let Some(labels) = labels {
            let hidden_value = labels.get(HIDDEN_LABEL_NAME);
            match hidden_value {
                Some(value) => value != "true",
                None => true,
            }
        } else {
            true
        }
    }

    /// 获取数据库连接（通过store_service）
    pub fn get_database_connection(&self) -> &sea_orm::DatabaseConnection {
        self.store_service.connection()
    }
}

/// 角色服务工厂函数
/// 
/// 用于在依赖注入容器中创建RoleServiceDI实例
pub fn create_role_service_di(store_service: Arc<ExtensionStoreService>) -> Result<RoleServiceDI> {
    Ok(RoleServiceDI::new(store_service))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::di::ServiceContainer;
    use crate::di::services::{DatabaseService, ConfigService};
    use crate::config::{Configs, Server, DataBase, Log, Jwt, Cert};

    fn create_test_config() -> Configs {
        Configs {
            server: Server {
                name: "test".to_string(),
                address: "127.0.0.1:8080".to_string(),
                ssl: false,
            },
            database: DataBase {
                database_url: "sqlite::memory:".to_string(),
            },
            log: Log {
                filter_level: "info".to_string(),
                with_ansi: true,
                to_stdout: true,
                directory: "./logs".to_string(),
                file_name: "test.log".to_string(),
                rolling: "daily".to_string(),
            },
            jwt: Jwt {
                jwt_secret: "test_secret".to_string(),
                jwt_exp: 3600,
            },
            cert: Cert {
                cert: "test.pem".to_string(),
                key: "test.key".to_string(),
            },
        }
    }

    #[tokio::test]
    async fn test_role_service_creation() {
        let container = ServiceContainer::new();
        
        // 注册配置服务
        let config = create_test_config();
        container.register_singleton::<ConfigService, _>(move |_| {
            Ok(ConfigService::new(config.clone()))
        }).unwrap();

        // 测试配置服务解析
        let config_service = container.resolve::<ConfigService>().unwrap();
        assert_eq!(config_service.config().server.name, "test");
    }

    #[tokio::test]
    async fn test_role_service_dependencies() {
        // 这里可以测试角色服务的依赖注入
        // 由于需要数据库连接，暂时跳过实际的数据库操作测试
    }

    #[tokio::test]
    async fn test_contains_super_role() {
        // 创建一个模拟的store_service
        // 这里需要实际的ExtensionStoreService实例，暂时跳过
    }
}
